﻿using iTool.Cloud.Center;
using iTool.Cloud.Center.Model;
using iTool.Clustering.Center;
using iTool.Clustering.Center.ServiceProvider;
using Microsoft.Extensions.Options;
using Orleans.Configuration;
using System;
using System.Linq;
using System.Threading.Tasks;

namespace Orleans.Runtime.MembershipService
{
    internal class iCenterClusteringProvider : IMembershipTable
    {
        private IClusterServerService grain;
        private ClusterOptions clusterOptions;

        public iCenterClusteringProvider(iCenterClusterClient client, IOptions<ClusteringStaticOptions> options, IOptions<ClusterOptions> clusterOptions)
        {
            //var builder = new iToolClientBuilder();
            //builder.UseiCenterClustering(options.Value);
            //var client = builder.BuildAndConnectAsync().Result;
            this.clusterOptions = clusterOptions.Value;
            this.grain = client.GetGrain<IClusterServerService>((long)(new Random().Next(111_111_111, 999_999_999)), this.clusterOptions.ToKeyString());
        }

        public async Task InitializeMembershipTable(bool tryInitTableVersion) => await this.grain.InitializeMembershipTable(tryInitTableVersion);

        public async Task DeleteMembershipTableEntries(string clusterId) => await this.grain.DeleteMembershipTableEntries(clusterId);

        public async Task<MembershipTableData> ReadRow(SiloAddress key)
        {
            MembershipTableOptions options = await this.grain.ReadRow(key.ToParsableString());
            return new MembershipTableData(
                options.MembershipOptionList?.Select(x => Tuple.Create(x.ToEntry(), x.Etag)).ToList(),
                options.ClusterTableVersionOptions?.ToTableVersion());
        }

        public async Task<MembershipTableData> ReadAll()
        {
            MembershipTableOptions options = await this.grain.ReadAll();
            return new MembershipTableData(
                options.MembershipOptionList?.Select(x => Tuple.Create(x.ToEntry(), x.Etag)).ToList(),
                options.ClusterTableVersionOptions?.ToTableVersion());
        }

        public async Task<bool> InsertRow(MembershipEntry entry, TableVersion tableVersion)
        {
            //tableVersion.ToString(CultureInfo.InvariantCulture)
            return await this.grain.InsertRow(
                entry.SiloAddress.ToParsableString(),
                MembershipOptions.Create(entry),
                ClusterTableVersionOptions.Create(tableVersion));
        }

        public async Task<bool> UpdateRow(MembershipEntry entry, string etag, TableVersion tableVersion)
        {
            return await this.grain.UpdateRow(
                entry.SiloAddress.ToParsableString(),
                MembershipOptions.Create(entry),
                etag,
                ClusterTableVersionOptions.Create(tableVersion));
        }

        public async Task UpdateIAmAlive(MembershipEntry entry) => await this.grain.UpdateIAmAlive(entry.SiloAddress.ToParsableString(), entry.IAmAliveTime);

        public async Task CleanupDefunctSiloEntries(DateTimeOffset beforeDate) => await this.grain.CleanupDefunctSiloEntries(beforeDate);

    }
}
